//======================================================================
//    We will gone,the word kept  
//======================================================================
`timescale 1ps/1ps
//=====v1.0====2021.11.10
// tm_axiw.w(pwrite,pwaddr,pwdata)

module tm_maxistx
# (parameter DW = 128)
(
	input				sys_rst								,
	input				sys_clk								,

  // AXI Streaming Master Signals (Read side)
    output  reg	                             m_axis_tvalid,
    input                               	m_axis_tready,
    output reg[DW-1:0]			    m_axis_tdata,
    output reg[DW/8-1:0]     		m_axis_tkeep,//tkeep means byte is used or noused（novalid）；tstrbmeans data is used or not ，but the position should be keep
    output reg                             	m_axis_tlast
  );
//=======================================================================
initial begin
	m_axis_tvalid = 0;
    m_axis_tlast = 0;
end

//initial begin
    /*task_vld = 0;
    forever begin
        @ (posedge tx_clk);
        if(task_vld)begin
    	tx_en = tx_en_tmp;
    	tx_data = tx_data_tmp;
        end
        else begin
    	tx_en = 0;
    	tx_data = 8'b0;
        end
    
	*/
//end
bit[7:0]	tx_data_tmp;
bit[DW/8-1:0] 			tkeep;
bit[7:0]	memory_tmp[DW/8-1:0];


//===fixed signal output==
/*//=======================================================================
task pkt_head(input	int		len,
	     input	bit[47:0]		dmac,
	     input	bit[47:0]		smac,
	     input	bit[15:0]		ptype,
	     input	bit[95:0]		l3_head,
	     input	bit[31:0]		sip,
	     input	bit[31:0]		dip,
	     input	bit[7:0]		payload0,
	     input	bit[8:0]		payload1,
	     input	bit[7:0]		payload2,
	     input	bit[8:0]		payload3,
	     output	string			pkt_content
					);
	   string	sub_data;
	  
	   pkt_content={};//清空字符串
		 sub_data.hextoa(dmac);
		 pkt_content={pkt_content,sub_data};
		 sub_data.hextoa(smac);
		 pkt_content={pkt_content,sub_data};
		 sub_data.hextoa(ptype);
		 pkt_content={pkt_content,sub_data};
		 sub_data.hextoa(l3_head);
		 pkt_content={pkt_content,sub_data};
			
		 for(int i=34; i<len; i++) begin
		   	 case(i%4)
		 		 		 0 : begin
		 		 		     sub_data.hextoa(payload0);
		 		 		     pkt_content={pkt_content,sub_data};
		 		 		 end
		 		 		 1 : begin
		 		 		     sub_data.hextoa(payload1);
		 		 		     pkt_content={pkt_content,sub_data};
		 		 		 end
		 		 		 2 : begin
		 		 		     sub_data.hextoa(payload2);
		 		 		     pkt_content={pkt_content,sub_data};
		 		 		 end
		 		 		 3 : begin
		 		 		     sub_data.hextoa(payload3);
		 		 		     pkt_content={pkt_content,sub_data};
		 		 		 end
		 		 		 default : ;
		   	 endcase
		 end
endtask
*/
genvar ig;
generate
	for(ig=0; ig<(DW/8); ig=ig+1) begin :block_g
	//先进入的字节，放到高位，这是我们习惯的顺序；xilinx习惯在低位.下面2句被注释的，是高位。
        //assign m_axis_tdata[(DW-ig*8-1):(DW-ig*8-8)] = memory_tmp[ig];
		//assign m_axis_tkeep[DW/8-ig-1]				 = tkeep[ig] ;
	//先进入的字节，放到低位，xilinx习惯在低位，后续我们统一到xilinx模式
		assign m_axis_tdata[(ig*8+7):(ig*8)] = memory_tmp[ig];
		assign m_axis_tkeep[ig]				 = tkeep[ig] ;
		/*if (DW==8)
			assign m_axis_tdata = memory_tmp[0];
		else
			assign m_axis_tdata	= {m_axis_tdata[DW-1:DW-8],memory_tmp[ig]};
		*/
    end
endgenerate


task tx (input	string	pkt_content,	input	bit[1:0] data_mode );//00=裸数据；01=裸数据+CRC32；10=帧数据,需要+前导+CRC32；11=帧数据，需要+前导，不加CRC。
//获得数据
	int j ;
	int n ;	
	int jj;
    int			pkt_len;
    bit[7:0]    pkt_data[$];//数据
    string		data_tmp;
    bit[31:0]	crc_out;
    bit[31:0]	crc_reg;
	bit         s_done ;

	j = 0;
	n = 0;
    
    pkt_len = pkt_content.len();//获得字符串长度
    pkt_data = {};			//清空队列
    for(int i=0;i<(pkt_len/2);i=i+1)begin
        data_tmp = pkt_content.substr(i*2,i*2+1);//取出2个字符
        pkt_data[i] = data_tmp.atohex();//转换成数据放入队列
    end
    //-------------------------
    //crc
    crc_reg = 32'hffffffff;
    for(int m=0;m<pkt_data.size();m=m+1)begin
		crc_gen( crc_reg, pkt_data[m], crc_out ); 
        crc_reg = crc_out;
    end
    crc_out = {	crc_out[24],  crc_out[25], crc_out[26], crc_out[27], // Reverse bit order
                crc_out[28],  crc_out[29], crc_out[30], crc_out[31],
                crc_out[16],  crc_out[17], crc_out[18], crc_out[19],
                crc_out[20],  crc_out[21], crc_out[22], crc_out[23],
                crc_out[8],   crc_out[9],  crc_out[10], crc_out[11],
                crc_out[12],  crc_out[13], crc_out[14], crc_out[15],
                crc_out[0],   crc_out[1],  crc_out[2],  crc_out[3],
                crc_out[4],   crc_out[5],  crc_out[6],  crc_out[7]};
	if (data_mode==2'b01 || data_mode==2'b10) begin
	    pkt_data.push_back(~crc_out[31:24]);
		pkt_data.push_back(~crc_out[23:16]);
		pkt_data.push_back(~crc_out[15:8]);
		pkt_data.push_back(~crc_out[7:0]);
	end
    //-------------------------
	if (data_mode==2'b10 || data_mode==2'b11) begin
		//add 55 d5
		pkt_data.push_front(8'hd5);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
	end
    //------pkt_data init finished---------------------
    //send pkt,DW=8/16/32/64/128/256/512
    //置标记

	jj= pkt_data.size();
	@ (posedge sys_clk);
				#1ns;
	m_axis_tvalid = 1'b1;
	wait(m_axis_tready);
	while (j< jj) begin
		n=0;
		m_axis_tvalid = 1'b1;
		tkeep = 'd0;
		m_axis_tlast = 'd0;
		s_done = 'd0 ;

		while (n<DW/8 & !s_done) begin
			if (m_axis_tvalid && m_axis_tready) begin
				tx_data_tmp = pkt_data[j];
				//m_axis_tdata[n*8+7:n*8] = tx_data_tmp;
				memory_tmp[n]		= tx_data_tmp;
				tkeep[n]	= 1'b1;
				j=j+1;  
				n=n+1;
				
				if (j>= jj) begin
					m_axis_tlast = 'b1;	
					s_done = 'b1 ;
				end
				
			end
		end
		@ (posedge sys_clk);
				#1ns;
    end	
	m_axis_tvalid		 <= 'd0;
	tkeep <= 'd0;
	m_axis_tlast <= 'd0;

/*
    for(ig=0; ig<(DW/8-1); ig=ig+1) begin
        //m_axis_tdata[ig*8+7:ig*8] = memory_tmp[ig];
		if (DW==8)
			m_axis_tdata = memory_tmp[0];
		else
			m_axis_tdata	= {m_axis_tdata[DW-1:DW-8],memory_tmp[ig]};
		
    end
*/	
	
    /*// //send gap
    tx_en_tmp = 0;
    for(int k=0;k<gap_len;k++)begin
        tx_data_tmp = 8'b0;
        tx_en_tmp = 0;
        @ (posedge sys_clk);
        #1ns;
    end
    task_vld = 0;
	*/
    $display("<%0t>: %s send>>>>>>>>> 1 pkt \n",$time,pkt_data.size-8);
endtask
//=======================================================================
task add (input[15:0]	len,	input	bit[1:0] data_mode );//00=裸数据；01=裸数据+CRC32；10=帧数据,需要+前导+CRC32；11=帧数据，需要+前导，不加CRC。
//获得数据
	int j ;
	int n ;	
	int jj;
    int			pkt_len;
     bit[7:0]    pkt_data[$];//数据
	 bit[7:0]	cnt ;
    string		data_tmp;
    bit[31:0]	crc_out;
    bit[31:0]	crc_reg;
	bit         s_done ;

	j = 0;
	n = 0;
    
    pkt_len = len;//获得字符串长度
    pkt_data = {};			//清空队列
for(int i=0;i<(pkt_len);i=i+1)begin
        cnt = cnt+1;//取出2个字符
        pkt_data[i] = cnt;//转换成数据放入队列
    end
    //-------------------------
    //crc
    crc_reg = 32'hffffffff;
    for(int m=0;m<pkt_data.size();m=m+1)begin
		crc_gen( crc_reg, pkt_data[m], crc_out ); 
        crc_reg = crc_out;
    end
    crc_out = {	crc_out[24],  crc_out[25], crc_out[26], crc_out[27], // Reverse bit order
                crc_out[28],  crc_out[29], crc_out[30], crc_out[31],
                crc_out[16],  crc_out[17], crc_out[18], crc_out[19],
                crc_out[20],  crc_out[21], crc_out[22], crc_out[23],
                crc_out[8],   crc_out[9],  crc_out[10], crc_out[11],
                crc_out[12],  crc_out[13], crc_out[14], crc_out[15],
                crc_out[0],   crc_out[1],  crc_out[2],  crc_out[3],
                crc_out[4],   crc_out[5],  crc_out[6],  crc_out[7]};
	if (data_mode==2'b01 || data_mode==2'b10) begin
	    pkt_data.push_back(~crc_out[31:24]);
		pkt_data.push_back(~crc_out[23:16]);
		pkt_data.push_back(~crc_out[15:8]);
		pkt_data.push_back(~crc_out[7:0]);
	end
    //-------------------------
	if (data_mode==2'b10 || data_mode==2'b11) begin
		//add 55 d5
		pkt_data.push_front(8'hd5);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
	end
    //------pkt_data init finished---------------------
    //send pkt,DW=8/16/32/64/128/256/512
    //置标记

	jj= pkt_data.size();
	@ (posedge sys_clk);
				#1ns;
	m_axis_tvalid = 1'b1;
	wait(m_axis_tready);
	while (j< jj) begin
		n=0;
		m_axis_tvalid = 1'b1;
		tkeep = 'd0;
		m_axis_tlast = 'd0;
		s_done = 'd0 ;

		while (n<DW/8 && ~s_done) begin
			if (m_axis_tvalid && m_axis_tready) begin
				tx_data_tmp = pkt_data[j];
				//m_axis_tdata[n*8+7:n*8] = tx_data_tmp;
				memory_tmp[n]		= tx_data_tmp;
				tkeep[n]	= 1'b1;
				j=j+1;  
				n=n+1;
				
				if (j>= jj) begin
					m_axis_tlast = 'b1;	
					s_done = 'b1;
				end
				
			end
		end
		@ (posedge sys_clk);
				#1ns;
    end	
	m_axis_tvalid		 <= 'd0;
	tkeep <= 'd0;
	m_axis_tlast <= 'd0;
$display("<%0t>: %s gen  pkt \n",$time,pkt_data.size-8);

endtask
///******************len = string+cnt**************************
task mux (input[15:0]	len,input	string	pkt_content,	input	bit[1:0] data_mode );//00=裸数据；01=裸数据+CRC32；10=帧数据,需要+前导+CRC32；11=帧数据，需要+前导，不加CRC。
//获得数据
	int j ;
	int n ;	
	int jj;
    int			pkt_len;
    bit[7:0]    pkt_data[$];//数据
    string	data_tmp ;
	bit[7:0]	cnt ;
    bit[31:0]	crc_out;
    bit[31:0]	crc_reg;
	bit         s_done;
	j = 0;
	n = 0;
	cnt = 0 ;

    pkt_len = pkt_content.len();;//获得字符串长度
    pkt_data = {};			//清空队列
    	//
		for(int i=0;i<len;i=i+1)begin
			if (i<(pkt_len/2) ) begin
        		data_tmp = pkt_content.substr(i*2,i*2+1);//取出2个字符
        		pkt_data[i] = data_tmp.atohex();//转换成数据放入队列
			end else begin
				cnt = cnt+1;//取出2个字符
        		pkt_data[i] = cnt;//转换成数据放入队列
			end
		end
		
    //-------------------------
    //crc
    crc_reg = 32'hffffffff;
    for(int m=0;m<pkt_data.size();m=m+1)begin
		crc_gen( crc_reg, pkt_data[m], crc_out ); 
        crc_reg = crc_out;
    end
    crc_out = {	crc_out[24],  crc_out[25], crc_out[26], crc_out[27], // Reverse bit order
                crc_out[28],  crc_out[29], crc_out[30], crc_out[31],
                crc_out[16],  crc_out[17], crc_out[18], crc_out[19],
                crc_out[20],  crc_out[21], crc_out[22], crc_out[23],
                crc_out[8],   crc_out[9],  crc_out[10], crc_out[11],
                crc_out[12],  crc_out[13], crc_out[14], crc_out[15],
                crc_out[0],   crc_out[1],  crc_out[2],  crc_out[3],
                crc_out[4],   crc_out[5],  crc_out[6],  crc_out[7]};
	if (data_mode==2'b01 || data_mode==2'b10) begin
	    pkt_data.push_back(~crc_out[31:24]);
		pkt_data.push_back(~crc_out[23:16]);
		pkt_data.push_back(~crc_out[15:8]);
		pkt_data.push_back(~crc_out[7:0]);
	end
    //-------------------------
	if (data_mode==2'b10 || data_mode==2'b11) begin
		//add 55 d5
		pkt_data.push_front(8'hd5);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
		pkt_data.push_front(8'h55);
	end
    //------pkt_data init finished---------------------
    //send pkt,DW=8/16/32/64/128/256/512
    //置标记

	jj= pkt_data.size();
	@ (posedge sys_clk);
				#1ns;
	m_axis_tvalid = 1'b1;
	wait(m_axis_tready);
	while (j< jj) begin
		n=0;
		m_axis_tvalid = 1'b1;
		tkeep = 'd0;
		m_axis_tlast = 'd0;
		s_done = 'd0 ;

		while (n<DW/8 & !s_done) begin
			if (m_axis_tvalid && m_axis_tready) begin
				tx_data_tmp = pkt_data[j];
				//m_axis_tdata[n*8+7:n*8] = tx_data_tmp;
				memory_tmp[n]		= tx_data_tmp;
				tkeep[n]	= 1'b1;
				j=j+1;  
				n=n+1;
				
				if (j>= jj) begin
					m_axis_tlast = 'b1;	
					s_done = 'b1 ;
				end
				
			end
		end
		@ (posedge sys_clk);
				#1ns;
    end	
	m_axis_tvalid		 <= 'd0;
	tkeep <= 'd0;
	m_axis_tlast <= 'd0;
$display("<%0t>: %s gen  mux \n",$time,pkt_data.size-8);

endtask
//*************************crc*************************************
	
task crc_gen(input bit[31:0]	crc,input   bit  [7:0]  d,output  bit  [31:0] o_crc);

begin
  o_crc[31] = crc[29]^d[2] ^ crc[23];
  o_crc[30] = crc[31]^d[0] ^ crc[28]^d[3] ^ crc[22];
  o_crc[29] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[27]^d[4] ^ crc[21];
  o_crc[28] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[26]^d[5] ^ crc[20];
  o_crc[27] = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[25]^d[6] ^ crc[19];
  o_crc[26] = crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[24]^d[7] ^ crc[18];
  o_crc[25] = crc[27]^d[4] ^ crc[26]^d[5] ^ crc[17];
  o_crc[24] = crc[31]^d[0] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[16];
  o_crc[23] = crc[30]^d[1] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[15];
  o_crc[22] = crc[24]^d[7] ^ crc[14];
  o_crc[21] = crc[29]^d[2] ^ crc[13];
  o_crc[20] = crc[28]^d[3] ^ crc[12];
  o_crc[19] = crc[31]^d[0] ^ crc[27]^d[4] ^ crc[11];
  o_crc[18] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[26]^d[5] ^ crc[10];
  o_crc[17] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[25]^d[6] ^ crc[9];
  o_crc[16] = crc[29]^d[2] ^ crc[28]^d[3] ^ crc[24]^d[7] ^ crc[8];
  o_crc[15] = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[7];
  o_crc[14] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[6];
  o_crc[13] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[5];
  o_crc[12] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[4];
  o_crc[11] = crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[3];
  o_crc[10] = crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7] ^ crc[2];
  o_crc[9]  = crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[1];
  o_crc[8]  = crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[0];
  o_crc[7]  = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7];
  o_crc[6]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6];
  o_crc[5]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7];
  o_crc[4]  = crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7];
  o_crc[3]  = crc[31]^d[0] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[25]^d[6];
  o_crc[2]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[24]^d[7];
  o_crc[1]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[25]^d[6] ^ crc[24]^d[7];
  o_crc[0]  = crc[30]^d[1] ^ crc[24]^d[7];
end
endtask

           

endmodule


